#pragma once
#include "util/noncopyable.h"
#include "util/mutex.h"

namespace net_tools::util
{
  namespace detail
  {
    struct Memorypool_point
    {
      Memorypool_point()
      {
        before_ = nullptr;
        next_ = nullptr;
        size_ = 0;
      };
      Memorypool_point *before_;
      Memorypool_point *next_;
      size_t size_;
    };

  } // namespace detail
  class Memorypool : util::noncopyable
  {
  public:
    Memorypool(size_t block_size, size_t block_number);
    ~Memorypool();
    //参数:要取用的区块数量
    void *Get_memory_unlocked(size_t block_number);
    void Free_memory_unlocked(void *paddress);
    void *Get_memory_locked(size_t block_number);
    void Free_memory_locked(void *paddress);

  private:
    //地址转换
    void *Change_data_to_block(void *address);
    //地址转换
    void *Change_block_to_data(detail::Memorypool_point *address);
    //链表插入 pbfore -> pnext => pbfore -> pmemory_pool_point -> pnext
    void Point_insert(detail::Memorypool_point *pbefore, detail::Memorypool_point *pmemory_pool_point);
    //链表删除 pbfore -> pmemory_pool_point -> pnext => pbfore -> pnext
    void Point_cut(detail::Memorypool_point *pmemory_pool_point); //将可用节点变为占用节点 切断前后连接
    //初始记录块创建
    //返回首位记录块
    detail::Memorypool_point *Point_create(void *paddress, const size_t size);
    //根据记录块首部创建尾部记录块
    void Point_back_create(detail::Memorypool_point *paddress);

    void *pmemory_data_;     //数据块起始地址
    void *pmemory_data_end_; //数据块结束地址
    void *pmemory_pool_;     //链表起始地址 及内存池起始地址

    detail::Memorypool_point *help_point_head_;
    detail::Memorypool_point *help_point_back_;

    size_t memory_pool_size_;      //整个内存池大小
    size_t memory_pool_data_size_; //内存池数据大小

    size_t block_number_; //数据块块数量
    size_t block_size_;   //数据块块大小
    size_t block_size_move_;
    size_t free_block_number_;

    util::Mutex mutex_;
  };

} // namespace net_tools::util